package com.dongdongshop.service.impl;

import cn.hutool.json.JSONObject;
import com.dongdongshop.mapper.TbSeckillGoodsMapper;
import com.dongdongshop.mapper.TbSeckillOrderMapper;
import com.dongdongshop.pojo.TbSeckillGoods;
import com.dongdongshop.pojo.TbSeckillGoodsExample;
import com.dongdongshop.pojo.TbSeckillOrder;
import com.dongdongshop.service.SeckillService;
import com.dongdongshop.utils.IdWorker;
import com.dongdongshop.utils.RedisKey;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
@DubboService
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private TbSeckillGoodsMapper seckillGoodsMapper;
    @Resource
    private TbSeckillOrderMapper seckillOrderMapper;
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    // 秒杀预热 ,将数据存入缓存当中
    @Override
    public void hotPrepare() {
        TbSeckillGoodsExample example = new TbSeckillGoodsExample();
        TbSeckillGoodsExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo("1");  // 1 代表已审核
        Date date = new Date();  //当前时间
        criteria.andStartTimeLessThanOrEqualTo(date);  // 开始时间小于或等于当前时间
        criteria.andEndTimeGreaterThanOrEqualTo(date); // 结束时间大于或等于当前时间

       /* Optional.ofNullable(seckillGoodsMapper.selectByExample(example)).ifPresent(li ->{
            li.stream().forEach(goods -> redisTemplate.opsForHash().put(RedisKey.SECKILLGOODS,goods.getId(),goods));
        });*/

        List<TbSeckillGoods> seckillGoods = seckillGoodsMapper.selectByExample(example);
        //将redis 的string类型实现 序列化
       // redisTemplate.setValueSerializer(new StringRedisSerializer());
        //判断 seckillGoods 存在的话,写入缓存,完成预热
        if (seckillGoods != null){
            for (TbSeckillGoods seckillGood : seckillGoods) {
                redisTemplate.opsForHash().put(RedisKey.SECKILLGOODS,seckillGood.getId(),seckillGood);
                // 同步库存信息,把 预减的库存放入redis中
               /* redisTemplate.boundValueOps(RedisKey.STOCK_COUNT+seckillGood.getId())
                        .set(seckillGood.getStockCount().toString());*/
                stringRedisTemplate.opsForValue().set(RedisKey.STOCK_COUNT+seckillGood.getId(),seckillGood.getStockCount().toString());

            }
        }
    }

    // 从缓存中查取数据
    @Override
    public List<TbSeckillGoods> getSeckillList() {
        List<TbSeckillGoods> values = redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).values();
        return values;
    }

    //查询抢购页面信息
    @Override
    public TbSeckillGoods getSeckillById(Long seckillId) {
        TbSeckillGoods goods = (TbSeckillGoods) redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).get(seckillId);
        return goods;
    }


    @Override
    public Long createOrder(Long userId, Long seckillId) {
        /*TbSeckillGoods seckillGoods = getSeckillById(seckillId);
        // 秒杀商品已下架
        if (seckillGoods == null){
            return -1L;
        }
        //已卖完
        if (seckillGoods.getStockCount() == 0){
            return -1L;
        }
        // 先减库存
        seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
        // 放回缓存
        redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).put(seckillId,seckillGoods);
        // 已卖完 将缓存数据删掉, 同步数据库中
        if (seckillGoods.getStockCount() == 0){
            redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).delete(seckillId);
            seckillGoodsMapper.updateByPrimaryKey(seckillGoods);
        }*/
        // 改造代码
        String s = stringRedisTemplate.opsForValue().get(RedisKey.STOCK_COUNT + seckillId);
        Long stockCount = Long.valueOf(s);
        if (stockCount == 0){
            return -1L;
        }

        //减库存 redis 中自减 1
        Long decrement = stringRedisTemplate.opsForValue().decrement(RedisKey.STOCK_COUNT + seckillId);
        // 判断 减过之后的 库存 是否等于 0
        if (decrement == 0){
            // 等于 0 , 说明 已售空,删除缓存数据,同步数据库
            redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).delete(seckillId);
            TbSeckillGoods goods = (TbSeckillGoods) redisTemplate.boundHashOps(RedisKey.SECKILLGOODS).get(seckillId);
            goods.setStockCount(0);
            seckillGoodsMapper.updateByPrimaryKey(goods);
        }

        // 发送 MQ 消息
        JSONObject json = new JSONObject();
        json.putOpt("userId", userId);
        json.putOpt("seckillId",seckillId);
        rocketMQTemplate.convertAndSend("seckill_topic",json.toString());

        return 1L;
    }

    //根据用户 id 去获取缓存中的 订单 id
    @Override
    public Long getOrderId(Long userId) {
        String o = (String) stringRedisTemplate.opsForHash().get(RedisKey.ORDERIDS, String.valueOf(userId));
        Long orderId = Long.valueOf(o);
        return orderId;
    }
}
